package com.menghao.sso.server.repository.customer;

import com.google.common.collect.Iterables;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>自定义查询规范.<br>
 *
 * @author 17070717.
 * @version 2017/11/6.
 */
public class CustomerSpecification<T> {

    @SuppressWarnings("unchecked")
    public static <T> Specification<T> byProperty(EntityManager entityManager, T entity) {

        final Class<T> clazz = (Class<T>) entity.getClass();
        return new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                EntityType<T> entityType = entityManager.getMetamodel().entity(clazz);
                if (null != entityType && entityType.getDeclaredAttributes().size() > 0) {
                    /*
                        泛型1-属性所在类的类型 泛型2-属性自身类型
                     */
                    for (Attribute<T, ?> attribute : entityType.getDeclaredAttributes()) {
                        Object value = ReflectionUtils.getField((Field) attribute.getJavaMember(), entity);
                        if (value != null) {
                            if (value.getClass().isInstance(String.class) && StringUtils.hasLength((String) value)) {
                                predicateList.add(criteriaBuilder.like(
                                        root.get(attribute.getName()), "%" + value + "%"));
                            } else {
                                predicateList.add(criteriaBuilder.equal(
                                        root.get(attribute.getName()), value));
                            }
                        }
                    }
                }
                return predicateList.isEmpty() ? criteriaBuilder.conjunction() : criteriaBuilder.and(
                        Iterables.toArray(predicateList, Predicate.class));
            }
        };

    }
}
